<template>
  <button class="bk-button box-shadow" :disabled="disabled" :class="classList" @click="$emit('click', $event)">
    <slot></slot>
  </button>
</template>

<script>
export default {
  name: 'bk-button',
  props: {
    type: {
      type: String,
      default: 'default'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    shadow: {
      type: Boolean,
      default: true
    },
    line: {
      type: Boolean,
      default: false
    },
    text: {
      type: Boolean,
      default: false
    },
    block: {
      type: Boolean,
      default: false
    },
    //  波纹特效
    ripple: {
      type: Boolean,
      default: true
    }
  },
  mounted () {
    this.$el.addEventListener('mousedown', this.mousedown)
    this.$el.addEventListener('mouseup', this.mouseup)
  },
  destroyed () {
    this.$el.removeEventListener('mousedown', this.mousedown)
    this.$el.removeEventListener('mouseup', this.mouseup)
  },
  methods: {
    mousedown (event) {
      if (this.ripple) this.createRipple(event)
    },
    mouseup (event) {
      if (this.ripple) this.removeRipple()
    },

    createRipple (event) {
      if (!this.ripple) return

      const container = this.$el
      const { x, y, centerX, centerY, size } = this.computeRippleStyles(container, event)
      const ripple = document.createElement('div')
      ripple.classList.add('bk-ripple')
      ripple.style.opacity = `0`
      ripple.style.transform = `translate(${x}px, ${y}px) scale3d(.3, .3, .3)`
      ripple.style.width = `${size}px`
      ripple.style.height = `${size}px`
      // 记录水波的创建时间
      ripple.dataset.createdAt = String(performance.now())

      const { position } = window.getComputedStyle(container)
      container.style.overflow = 'hidden'
      position === 'static' && (container.style.position = 'relative')

      container.appendChild(ripple)

      window.setTimeout(() => {
        ripple.style.transform = `translate(${centerX}px, ${centerY}px) scale3d(1, 1, 1)`
        ripple.style.opacity = `.25`
      })
    },
    removeRipple () {
      if (!this.ripple) return
      const container = this.$el
      const ripples = container.querySelectorAll('.bk-ripple')
      if (!ripples.length) return

      const lastRipple = ripples[ripples.length - 1]
      // 通过水波的创建时间计算出扩散动画还需要执行多久，确保每一个水波都完整的执行了扩散动画
      const delay = 300 - performance.now() + Number(lastRipple.dataset.createdAt)

      setTimeout(() => {
        lastRipple.style.opacity = `0`
        setTimeout(() => {
          if (lastRipple.parentNode) {
            lastRipple.parentNode.removeChild(lastRipple)
          }
        }, 300)
      }, delay)
    },
    computeRippleStyles (element, event) {
      const { top, left } = element.getBoundingClientRect()
      const { clientWidth, clientHeight } = element

      const radius = Math.sqrt(clientWidth ** 2 + clientHeight ** 2) / 2
      const size = radius * 2

      const localX = event.clientX - left
      const localY = event.clientY - top

      const centerX = (clientWidth - radius * 2) / 2
      const centerY = (clientHeight - radius * 2) / 2

      const x = localX - radius
      const y = localY - radius

      return { x, y, centerX, centerY, size }
    }
  },
  computed: {
    classList () {
      return [
        `bk-button-${this.type}`,
        this.disabled ? 'bk-button-disabled' : '',
        this.line ? 'bk-button-line' : '',
        this.text ? 'bk-button-text' : '',
        this.shadow ? 'bk-button-shadow' : '',
        this.block ? 'bk-button-block' : ''
      ]
    },
    isMobile () {
      return /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)
    }
  }
}
</script>

<style scoped>
  .bk-button {
    padding: 8px 30px;
    overflow: hidden;
    z-index: 1;
    border: 0;
    border-radius: 5px;
    position: relative;
  }
  .bk-button-hover { transform: translate(1px, 1px) }
  .bk-button-shadow { box-shadow: 1px 1px 5px rgba(0,0,0,.3) }
  .bk-button-block {
    width: 100%;
    display: block;
  }

  .bk-button-line {
    background: transparent;
    box-shadow: none;
  }
  .bk-button-text {
    background: transparent;
    box-shadow: none;
  }

  .bk-button-default {
    background: #F5F5F5;
    color: #000;
  }
  .bk-button-default.bk-button-line {
    border: 1px solid #000;
    color: #000;
  }
  .bk-button-default.bk-button-line { color: #000 }

  .bk-button-primary {
    background: #1989FA;
    color: #fff;
  }
  .bk-button-primary.bk-button-line {
    border: 1px solid #1989FA;
    color: #1989FA;
  }
  .bk-button-primary.bk-button-text { color: #1989FA }

  .bk-button-info {
    background: #00AFEF;
    color: #fff;
  }
  .bk-button-info.bk-button-line {
    border: 1px solid #00AFEF;
    color: #00AFEF;
  }
  .bk-button-info.bk-button-text { color: #00AFEF }

  .bk-button-success {
    background: #00C48F;
    color: #fff;
  }
  .bk-button-success.bk-button-line {
    border: 1px solid #00C48F;
    color: #00C48F;
  }
  .bk-button-success.bk-button-text { color: #00C48F }

  .bk-button-warning {
    background: #FF9F00;
    color: #fff;
  }
  .bk-button-warning.bk-button-line {
    border: 1px solid #FF9F00;
    color: #FF9F00;
  }
  .bk-button-warning.bk-button-text { color: #FF9F00 }

  .bk-button-danger {
    background: #F44336;
    color: #fff;
  }
  .bk-button-danger.bk-button-line {
    border: 1px solid #F44336;
    color: #F44336;
  }
  .bk-button-danger.bk-button-text { color: #F44336 }

  >>>.bk-ripple {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;
    border-radius: 50%;
    background-color: currentColor;
    opacity: 0;
    transition: transform 0.2s cubic-bezier(0.68, 0.01, 0.62, 0.6), opacity 0.08s linear;
    will-change: transform, opacity;
    pointer-events: none;
  }

</style>
